home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / m2 / cat3src / cat / msgwindo.i < prev    next >
Text File  |  1997-10-26  |  69KB  |  1,898 lines

  1. IMPLEMENTATION MODULE MsgWindow;
  2.  
  3. FROM SYSTEM     IMPORT  TSIZE, ADDRESS, ADR, CALLSYS, CADR, BYTE, ASSEMBLER;
  4.  
  5.  
  6. (* MM2-Module *)
  7. IMPORT Block, Strings, StrConv, GrafBase, BinOps, MOSGlobals,
  8.        Keyboard;
  9. FROM Keyboard  IMPORT SpecialCode;
  10. FROM Storage    IMPORT ALLOCATE, DEALLOCATE;
  11.  
  12.  
  13. (* Magic-Module *)
  14. IMPORT MagicAES, MagicVDI, MagicDOS, MagicFSM, mtTextfiles, mtAlerts, mtAppl,
  15.        mtUtils, mtDials, mtPopups, MagicXBIOS;
  16. FROM MagicSys   IMPORT Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7,
  17.                        Bit8, Bit9, Bit10, Bit11, Bit12, Bit13, Bit14, Bit15;
  18.  
  19.  
  20. (* CAT-Module *)
  21. IMPORT ARCStarter, CatFiles, CatTypes, MTE, MTEdit2, 
  22.        CatEdit, FontSelect, WdwManager, VDIStandards, VDIUtil, ConfVars,
  23.        CatGlobal, EditTypes, MausTauschrsc, grinTools, ListHelp,
  24.        grin, data, dataSys, QuickSort, Varnames, Infofiles, RectFuncs,
  25.        GroupSelect, WinDials, CatHelp;
  26.  
  27. FROM CatGlobal   IMPORT OpenName;
  28. FROM MTPaths     IMPORT MessagePath, DataPath, ExportPath, ImportPath, ARCName;
  29. IMPORT ConvertDate;
  30. FROM UserInformation IMPORT UserBLK, batchProcess;
  31. FROM Void        IMPORT v;
  32.  
  33. IMPORT Messages;
  34. FROM Messages   IMPORT MessageType;
  35.  
  36. CONST msgWindowTitle0   = '[CAT] '+0C;
  37.       msgWindowTitle    = 'Nachrichtenauswahl'+0C;
  38.       msgGroup          = 'Gruppe:'+0C;
  39.       msgAn             = 'An:'+0C;
  40.       msgWegen          = 'Wegen:'+0C;
  41.       msgNummer         = 'Nummer:'+0C;
  42.       msgSend           = 'Status: Versenden'+0C;
  43.       msgKlemm          = 'Status: Zurckhalten'+0C;
  44.       msgSize           = 'Gr”že:'+0C;
  45.       msgBytes          = 'Bytes'+0C;
  46.       msgDate           = 'Datum:'+0C;
  47.       msgCopy           = 'Kopie'+0C;
  48.       msgForward        = 'Weiterleitung'+0C;
  49.       msgGrpComm        = 'Gruppenkommentar'+0C;
  50.       msgComm           = 'Kommentar'+0C;
  51.       msgMail           = 'Nachricht'+0C;
  52.       msgAnswer         = 'Antwort'+0C;
  53.       msgPersAnswer     = 'Privatkommentar'+0C;
  54.       msgPrivate        = 'Pers”nliche'+0C;
  55.  
  56.       msgNoHdrText      = 'HDR-Datei konnte nicht gelesen werden! Nachrichten bitte '+0C;
  57.       msgNoHdrText2     = 'immer nur ber dieses Modul l”schen, sonst gibt es diesen Fehler!'+0C;
  58.  
  59.  
  60. TYPE
  61.   msgWindowType = RECORD
  62.                     wdw         : INTEGER;      (* Windowhandle *)
  63.                     vdi         : INTEGER;      (* VDI-Handle   *)
  64.                     butWork,
  65.                     msgWork     : GrafBase.Rectangle; (* Workrectangle des Fensters *)
  66.                     isHidden    : BOOLEAN;
  67.                     list        : Messages.msgArrayPtr;
  68.                     sel         : INTEGER;      (* Nummer des zuletzt selektierten Eintrags *)
  69.                     windLines   : INTEGER;      (* Anzahl der Zeilen im Fenster *)
  70.                     number      : INTEGER;      (* Nummer des Fensters im Modul *)
  71.                     font, 
  72.                     fontSize    : INTEGER;      (* Font & Gr”že *)
  73.                     startPos    : INTEGER;      (* aktuelle Top-Position *)
  74.                     leftOffset  : INTEGER;
  75.                     maxPos      : INTEGER;      (* = messages *)
  76.                     maxWidth    : INTEGER;
  77.                     charHeight,                 (* Zeichensatzvariablen *)
  78.                     charWidth   : INTEGER;
  79.                     isFSM       : BOOLEAN;
  80.                     monoSpaced  : BOOLEAN;
  81.                   END;
  82.  
  83.      msgWdwPtr = POINTER TO msgWindowType;
  84.  
  85. TYPE        
  86.         Trick =  POINTER TO RECORD
  87.                    CASE : BOOLEAN OF
  88.                      TRUE : wert: INTEGER;|
  89.                      FALSE: hi: CHAR;
  90.                             lo: CHAR;|
  91.                    END;
  92.                  END;
  93.  
  94.  
  95. VAR 
  96.         lineDist        : INTEGER;
  97.         pixOffset       : INTEGER;
  98.         
  99.         msgWindow       : msgWindowType;
  100.  
  101.         distSel  : mtUtils.tObjcTree;
  102.         butBox   : mtUtils.tObjcTree;
  103.         
  104.         inOpen   : BOOLEAN;     (* Semaphore fr snapWdw *)
  105.         init     : INTEGER;
  106.  
  107. (*=========================================================================*)
  108. (* Hier kommen jetzt die Prozeduren zur Verwaltung des Messagefensters     *)
  109. (*=========================================================================*)
  110.  
  111. (* ---------------------- Font-Funktionen ----------------------- *)
  112. PROCEDURE iMsgSetFont (wdw : INTEGER; fnt, fntSize : INTEGER; redraw: BOOLEAN);
  113. (* Setzt den Font fr das Stichwortlistenfenster *)
  114.   VAR r : GrafBase.Rectangle;
  115. BEGIN
  116.   IF wdw = msgWindow.wdw
  117.   THEN
  118.     WITH msgWindow DO
  119.       font := fnt;
  120.       fontSize := fntSize;
  121.       FontSelect.SetFont (vdi, font, fontSize, FALSE, monoSpaced, isFSM, charWidth, charHeight);
  122.       (* Jetzt ist der Font gesetzt. Jetzt noch Window snappen und dann neu
  123.        * zeichnen lassen 
  124.        *)
  125.       maxWidth := 0;
  126.       v.bool := ConfVars.SetConfigInt (cfgFont, font);
  127.       v.bool := ConfVars.SetConfigInt (cfgFontSize, fontSize);
  128.       WdwManager.SetDocumentParms (wdw, 1, 2*charHeight+lineDist);
  129.       WdwManager.GetWdwSize (wdw, r);
  130.       WdwManager.SetWdwSize (wdw, r);
  131.       r := msgWork;
  132.       INC (r.x, pixOffset);
  133.       IF redraw THEN 
  134.         IF ~isHidden THEN WdwManager.RedrawWdw (wdw, r); END;
  135.         WdwManager.SetWdwDocument (wdw, GrafBase.LongRect{LONG(leftOffset), startPos, LONG(maxWidth), maxPos});
  136.       END;
  137.     END; (* WITH ed^ DO *)
  138.   END;
  139. END iMsgSetFont;
  140.  
  141. (*-------------- Selektion von Eintr„gen ----------------------*)
  142. PROCEDURE hasSelectedEntries (ptr : msgWdwPtr; VAR first : INTEGER): BOOLEAN;
  143.   VAR i : INTEGER;
  144. BEGIN
  145.   WITH ptr^ DO
  146.     FOR i := 0 TO maxPos DO
  147.       IF list^[i].selected THEN first := i; RETURN TRUE
  148.       END;
  149.     END;
  150.   END;
  151.   RETURN FALSE;
  152. END hasSelectedEntries;
  153.  
  154. PROCEDURE countSelectedEntries (ptr : msgWdwPtr) : CARDINAL;
  155.   VAR i : INTEGER;
  156.       (*$Reg *) counter : CARDINAL;
  157. BEGIN
  158.   WITH ptr^ DO
  159.     counter := 0;
  160.     FOR i := 0 TO maxPos DO
  161.       IF list^[i].selected THEN INC (counter)
  162.       END;
  163.     END;
  164.   END;
  165.   RETURN counter;
  166. END countSelectedEntries;
  167.  
  168. PROCEDURE redrawEntry (entry: INTEGER);
  169.   VAR rect : GrafBase.Rectangle;
  170. BEGIN
  171.   WITH msgWindow DO
  172.     IF (wdw < 0) OR isHidden THEN RETURN END;
  173.     IF entry > maxPos THEN RETURN END;
  174.     rect := msgWork;
  175.     INC (rect.x, pixOffset);
  176.     rect.y := rect.y + (entry - startPos) * (2*charHeight+lineDist);
  177.     rect.h := 2*charHeight + lineDist;
  178.     WdwManager.RedrawWdw (wdw, rect);
  179.   END;
  180. END redrawEntry;
  181.  
  182. PROCEDURE toggleEntry (ptr : msgWdwPtr; entry: INTEGER);
  183.   VAR rect : GrafBase.Rectangle;
  184. BEGIN
  185.   WITH ptr^ DO
  186.     IF (entry > maxPos) OR (entry < 0) THEN RETURN END;
  187.     list^[entry].selected := ~list^[entry].selected;
  188.     redrawEntry (entry);
  189.   END;
  190. END toggleEntry;
  191.  
  192. PROCEDURE deselectEntries (ptr : msgWdwPtr);
  193.   VAR i         : INTEGER;
  194.       rect      : GrafBase.Rectangle;
  195.       first     : BOOLEAN;
  196. BEGIN
  197.   WITH ptr^ DO
  198.     rect := msgWork;
  199.     INC (rect.x, pixOffset);
  200.     first := TRUE;
  201.     rect.h := 2*charHeight + lineDist;
  202.     FOR i := 0 TO maxPos DO
  203.       IF list^[i].selected
  204.       THEN
  205.         list^[i].selected := FALSE;
  206.         IF (i >= startPos) & (i <= startPos + windLines)
  207.         THEN 
  208.           (* redraw *)
  209.           IF first THEN 
  210.             rect.y := msgWork.y + (i - startPos) * (2*charHeight+lineDist);
  211.             first := FALSE
  212.           ELSE
  213.             rect.h := msgWork.y + (i - startPos + 1) * (2*charHeight+lineDist) - rect.y;
  214.           END;
  215.         END;
  216.       END;
  217.     END;
  218.     IF ~first THEN WdwManager.RedrawWdw (wdw, rect) END;;
  219.   END;
  220. END deselectEntries;
  221.  
  222. (*-------------- Funktionen fr WdwManager --------------------*)
  223. PROCEDURE AdjustTreePos (r: GrafBase.Rectangle; VAR rt : GrafBase.Rectangle);
  224. BEGIN
  225.   WITH butBox^[0] DO
  226.     obX := r.x;
  227.     obY := r.y;
  228.     obWidth := r.w;
  229.     rt.x := obX; rt.y := obY;
  230.     rt.w := obWidth; rt.h := obHeight+1;
  231.   END;
  232. END AdjustTreePos;
  233.  
  234. PROCEDURE rawRedraw (ptr : msgWdwPtr; clip : GrafBase.Rectangle);
  235.   (* Geht davon aus, daž RectFuncs.ClipRect gesetzt ist und nur Zeilen zu zeichnen sind! 
  236.    *)
  237.   
  238. VAR 
  239.     extend : ARRAY [0..3] OF GrafBase.Point;
  240.     i      : INTEGER;
  241.     width  : INTEGER;
  242.     xOutput, 
  243.     yOutput: INTEGER;
  244.     xOffset: INTEGER;
  245.     j      : INTEGER;
  246.     topLine: INTEGER;
  247.     tmpStr : CatTypes.String255;
  248.     msgName: CatTypes.String255;
  249.     msg    : Messages.msgInfo;
  250.     myClip : GrafBase.Rectangle;
  251.     fill   : GrafBase.Rectangle;
  252.     attrSet: BOOLEAN;
  253.     isStatus: BOOLEAN;
  254.     dt      : ConvertDate.Date;
  255.     ti      : ConvertDate.Time;
  256.     holdEff : BITSET;
  257. BEGIN
  258.   WITH ptr^ DO
  259.     topLine := startPos;
  260.     attrSet := FALSE;
  261.     i := 0;   (* Zeilenz„hler im Fenster *)
  262.     (* Nicht im Redrawbereich liegende Zeilen berspringen *)
  263.     WHILE (topLine <= maxPos) & ((msgWork.y + (i+1)*(2*charHeight+lineDist)) - 1 < clip.y) DO
  264.       INC (topLine);
  265.       INC(i);
  266.     END;
  267.     xOutput := msgWork.x + pixOffset - leftOffset;
  268.     yOutput := msgWork.y + i * (2*charHeight + lineDist) + (lineDist DIV 2) + charHeight-1;
  269.     (* Eintrag in Liste suchen *)
  270.     (* Jetzt zeichnen *)
  271.     myClip := clip;
  272.     v.int := MagicVDI.SetFillcolor (vdi, MagicAES.BLACK);
  273.     v.int := MagicVDI.SetTextcolor (vdi, CatGlobal.msgTextCol);
  274.     v.int := MagicVDI.SetWritemode (vdi, MagicVDI.TRANSPARENT);
  275.     WHILE (topLine <= maxPos) & (i <= msgWork.h DIV (2*charHeight+lineDist)) 
  276.           & (yOutput <= clip.h + charHeight-1) DO
  277.       msg := list^[topLine];
  278.       IF ~msg.hdrRead
  279.       THEN
  280.         Messages.ReadHdrInfo (msg, TRUE);
  281.         list^[topLine] := msg;
  282.       END;
  283.       IF msg.hdrRead
  284.       THEN
  285.         (* 1. Zeile: MSG001   An/Gruppe: <empf„nger/gruppenname>
  286.          * 2. Zeile: status   Wegen: 
  287.          *)
  288.         IF ~msg.sendMsg
  289.         THEN
  290.           IF mtAppl.Bitplanes > 1
  291.           THEN
  292.             v.int := MagicVDI.SetTextcolor (vdi, CatGlobal.msgHoldCol);
  293.           ELSE
  294.             CASE CatGlobal.msgHoldEff OF
  295.               0 : holdEff := {}; |
  296.               1 : holdEff := {MagicVDI.Fat}; |
  297.               2 : holdEff := {MagicVDI.Italic}; |
  298.               3 : holdEff := {MagicVDI.Light}; |
  299.             ELSE
  300.               holdEff := {};
  301.             END;
  302.             IF msg.toDelete 
  303.             THEN
  304.               INCL (holdEff, MagicVDI.Italic);
  305.             END;
  306.             v.bset := MagicVDI.SetTexteffect (vdi, holdEff);
  307.           END;
  308.         ELSIF msg.toDelete 
  309.         THEN
  310.           v.bset := MagicVDI.SetTexteffect (vdi, {MagicVDI.Italic});
  311.         END;
  312.         (* Jetzt die einzelnen Zeilenteile ausgeben *)
  313.         xOffset := 0;
  314.         Messages.Number2Name (msg.number, msgName);
  315.         VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput, msgName);
  316.         INC (xOffset, 8*charWidth); 
  317.         CASE msg.msgType OF
  318.           copyOwn, 
  319.           copyOther    : Strings.Assign (msgCopy, msgName, v.bool); |
  320.           forward      : Strings.Assign (msgForward, msgName, v.bool); |
  321.           groupcomment : Strings.Assign (msgGrpComm, msgName, v.bool); |
  322.           comment      : Strings.Assign (msgComm, msgName, v.bool); |
  323.           mail         : Strings.Assign (msgMail, msgName, v.bool); |
  324.           persanswer   : Strings.Assign (msgPersAnswer, msgName, v.bool); |
  325.           answer       : Strings.Assign (msgAnswer, msgName, v.bool); |
  326.           private      : Strings.Assign (msgPrivate, msgName, v.bool); |
  327.         ELSE
  328.         END;
  329.         isStatus := (msg.msgType = copyOther) OR (msg.msgType = copyOwn) 
  330.                     OR (msg.msgType = forward);
  331.         VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput, msgName);
  332.         INC (xOffset, 18*charWidth);
  333.         IF (msg.msgType = mail) OR (msg.msgType = comment) OR (msg.msgType = groupcomment)
  334.         THEN
  335.           VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput, Messages.msgDistr);
  336.           INC (xOffset, 8*charWidth);
  337.           VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput, Messages.msgDistribs [msg.dist]);
  338.           (*
  339.           CASE msg.dist OF 
  340.             dNone     : VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput, msgDNone); |
  341.             dLokal    : VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput, msgDLokal) |
  342.             dMausNet  : VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput, msgDMausNet) |
  343.             dNet      : VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput, msgDNet) |
  344.           ELSE
  345.           END;
  346.           *)
  347.           INC (xOffset, 10*charWidth);
  348.         ELSE
  349.           INC (xOffset, 18*charWidth);
  350.         END;
  351.         IF msg.sendMsg
  352.         THEN
  353.           VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput, msgSend);
  354.         ELSE
  355.           VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput, msgKlemm);
  356.         END;
  357.         INC (xOffset, INTEGER(LENGTH (msgKlemm)+2) * charWidth);
  358.         IF ~isStatus
  359.         THEN
  360.           VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput, msgSize);
  361.           INC (xOffset, INTEGER(LENGTH (msgSize)+1) * charWidth);
  362.           Strings.Assign (StrConv.LNumToStr (msg.size, 10, 0, ' '), msgName, v.bool);
  363.           VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput, msgName);
  364.           INC (xOffset, INTEGER(LENGTH (msgName)+1) * charWidth);
  365.           VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput, msgBytes);
  366.           INC (xOffset, INTEGER(LENGTH (msgBytes)+2) * charWidth);
  367.         END;
  368.         (* Jetzt noch Datum und Uhrzeit *)
  369.         VDIStandards.Text (isFSM, vdi, xOutput + xOffset, yOutput, msgDate);
  370.         INC (xOffset, INTEGER(LENGTH (msgDate)) * charWidth);
  371.         (* Datum und Zeit in String setzen *)
  372.         dt := ConvertDate.UnpackDate (msg.cDate);
  373.         ti := ConvertDate.UnpackTime (msg.cTime);
  374.         ConvertDate.DayToText (dt, 'GG, ', msgName);
  375.         ConvertDate.DateToText (dt, 'dd. GGG YYYY, ', tmpStr);
  376.         Strings.Append (tmpStr, msgName, v.bool);
  377.         ConvertDate.TimeToText (ti, 'HH:MM:SS Uhr', tmpStr);
  378.         Strings.Append (tmpStr, msgName, v.bool);
  379.         VDIStandards.Text (isFSM, vdi, xOutput + xOffset, yOutput, msgName);
  380.         INC (xOffset, INTEGER(LENGTH (msgName)+1) * charWidth);
  381.         width := xOffset;
  382.         
  383.         (* Zweite Zeile: 
  384.          * Gruppe/Empf„nger und dann Stichwort
  385.          *)
  386.         xOffset := charWidth;
  387.         IF (msg.msgType = comment) OR (msg.msgType = mail) OR (msg.msgType = groupcomment)
  388.         THEN
  389.           VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput+charHeight, msgGroup);
  390.           INC (xOffset, 8*charWidth);
  391.           VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput+charHeight, msg.group^);
  392.           INC (xOffset, INTEGER(LENGTH (msg.group^)+2)*charWidth);
  393.         ELSE
  394.           VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput+charHeight, msgAn);
  395.           INC (xOffset, 4*charWidth);
  396.           VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput+charHeight, msg.receiver^);
  397.           INC (xOffset, INTEGER(LENGTH (msg.receiver^)+2)*charWidth);
  398.         END;
  399.         xOffset := BinOps.HigherInt (xOffset, 26*charWidth);
  400.         VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput+charHeight, msgWegen);
  401.         INC (xOffset, 7*charWidth);
  402.         IF msg.topic # NIL
  403.         THEN
  404.           VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput+charHeight, msg.topic^);
  405.           INC (xOffset, INTEGER(LENGTH (msg.topic^) + 1) * charWidth);
  406.         END;
  407.         width := BinOps.HigherInt (width, xOffset);
  408.         maxWidth := BinOps.HigherInt (maxWidth, width+pixOffset);
  409.         IF msg.selected
  410.         THEN
  411.           fill.x := xOutput;
  412.           fill.y := yOutput - charHeight+1;
  413.           fill.w := xOutput + maxWidth - 1;
  414.           fill.h := yOutput + charHeight ;
  415.           (* Schreibmodus setzen *)
  416.           v.int := MagicVDI.SetWritemode (vdi, MagicVDI.XOR);
  417.           MagicVDI.FillRectangle(vdi, fill);
  418.           v.int := MagicVDI.SetWritemode (vdi, MagicVDI.TRANSPARENT);
  419.         END;
  420.         IF ~msg.sendMsg
  421.         THEN
  422.           IF mtAppl.Bitplanes > 1
  423.           THEN
  424.             v.int := MagicVDI.SetTextcolor (vdi, CatGlobal.msgTextCol);
  425.           ELSE
  426.             v.bset := MagicVDI.SetTexteffect (vdi, {});
  427.           END;
  428.         ELSIF msg.toDelete 
  429.         THEN
  430.           v.bset := MagicVDI.SetTexteffect (vdi, {});
  431.         END;
  432.       ELSE
  433.         (* Header konnte nicht gelesen werden! Name ausgeben und 
  434.          * dahinter Fehlermeldung 
  435.          *)
  436.         (* Jetzt die einzelnen Zeilenteile ausgeben *)
  437.         xOffset := 0;
  438.         Messages.Number2Name (msg.number, msgName);
  439.         VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput, msgName);
  440.         INC (xOffset, 8*charWidth); 
  441.         VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput, msgNoHdrText);
  442.         VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput+charHeight, msgNoHdrText2);
  443.         INC (xOffset, BinOps.HigherInt (INTEGER(LENGTH (msgNoHdrText)+1) * charWidth, INTEGER(LENGTH (msgNoHdrText2)+1) * charWidth));
  444.         width := xOffset;
  445.         maxWidth := BinOps.HigherInt (maxWidth, width+pixOffset);
  446.         IF msg.selected
  447.         THEN
  448.           fill.x := xOutput;
  449.           fill.y := yOutput - charHeight+1;
  450.           fill.w := xOutput + maxWidth - 1;
  451.           fill.h := yOutput + charHeight ;
  452.           (* Schreibmodus setzen *)
  453.           v.int := MagicVDI.SetWritemode (vdi, MagicVDI.XOR);
  454.           MagicVDI.FillRectangle(vdi, fill);
  455.           v.int := MagicVDI.SetWritemode (vdi, MagicVDI.TRANSPARENT);
  456.         END;
  457.       END;
  458.       INC(i);
  459.       INC (topLine);
  460.       INC (yOutput, 2*charHeight+lineDist);
  461.     END;
  462.     v.int := MagicVDI.SetWritemode (vdi, MagicVDI.REPLACE);
  463.     v.int := MagicVDI.SetFillcolor (vdi, CatGlobal.msgBackCol);
  464.   END (* WITH ptr *);
  465. END rawRedraw;
  466.  
  467. PROCEDURE drawMsgWdw (wdw, vdiH : INTEGER; special : ADDRESS; frame : GrafBase.Rectangle);
  468. VAR clip : GrafBase.Rectangle;
  469.     ptr  : msgWdwPtr;
  470.     oldMax : INTEGER;
  471. BEGIN
  472.   ptr := msgWdwPtr (special);
  473.   WITH ptr^ DO
  474.     IF (mtAppl.Bitplanes = 1) 
  475.     THEN
  476.       IF (CatGlobal.msgTextCol > 0) 
  477.       THEN
  478.         CatGlobal.msgBackCol := 0;
  479.       ELSE
  480.         IF CatGlobal.msgBackCol = 0 THEN CatGlobal.msgBackCol := 1 END;
  481.       END;
  482.     END;
  483.     clip := frame;
  484.     IF RectFuncs.rcIntersect (butWork, clip)
  485.     THEN
  486.       VDIUtil.SetTreeColor (butBox, CatGlobal.msgTextCol, CatGlobal.msgBackCol);
  487.       mtDials.DialDraw (butBox, 0, 8, clip, TRUE);
  488.       mtAppl.MouseOff();
  489.     END;
  490.     clip := frame;
  491.     IF RectFuncs.rcIntersect (msgWork, clip)
  492.     THEN
  493.       oldMax := maxWidth;
  494.       clip := RectFuncs.ClipRect (frame, msgWork);
  495.       clip.w := clip.x + clip.w - 1; 
  496.       clip.h := clip.y + clip.h -1;
  497.       
  498.       v.int := MagicVDI.SetFillcolor (vdi, CatGlobal.msgBackCol);
  499.       MagicVDI.FillRectangle(vdi, clip);
  500.       
  501.       IF clip.x = msgWork.x THEN
  502.         INC (clip.x, pixOffset);
  503.       END;
  504.       
  505.       clip.x := BinOps.LowerInt (clip.x, clip.w);
  506.  
  507.       WdwManager.SetClip (vdi, clip, FALSE);
  508.       
  509.       rawRedraw (ptr, clip);
  510.       
  511.       IF oldMax # maxWidth THEN 
  512.         WdwManager.SetWdwDocument (wdw, GrafBase.LongRect{LONG(leftOffset), startPos, LONG(maxWidth), maxPos});
  513.       END;
  514.     END;
  515.   END (* WITH ptr^ DO *);
  516. END drawMsgWdw;
  517.  
  518. PROCEDURE redrawButton (wdw: INTEGER; butBox: mtUtils.tObjcTree; ob: INTEGER);
  519.   VAR r : GrafBase.Rectangle;
  520. BEGIN
  521.   mtUtils.ObjcPos (butBox, ob, r.x, r.y);
  522.   DEC (r.x); DEC (r.y);
  523.   r.w := butBox^[ob].obWidth+1;
  524.   r.h := butBox^[ob].obHeight+1;
  525.   WdwManager.RedrawWdw (wdw, r);
  526. END redrawButton;
  527.  
  528. TYPE    changeInfo  = RECORD
  529.                         msg       : Messages.msgInfo;
  530.                         isCopy, 
  531.                         wasPrivate,
  532.                         isPrivate : BOOLEAN;
  533.                         grName    : CatTypes.String255;
  534.                         lastName  : CatTypes.String255;
  535.                         select    : INTEGER;
  536.                         exitBut   : INTEGER;
  537.                       END;
  538.         changeInfoPtr = POINTER TO changeInfo;
  539.                         
  540.  
  541.   PROCEDURE redrawGrName (tree: mtUtils.tObjcTree);
  542.     VAR x1, y1 : INTEGER;
  543.   BEGIN
  544.     mtUtils.ObjcArea (tree, MausTauschrsc.chgruppe, v.r);
  545.     mtUtils.ObjcPos (tree, MausTauschrsc.chgrstr, x1, y1);
  546.     INC (v.r[2], v.r[0]-x1);
  547.     INC (v.r[3], v.r[1]-y1);
  548.     v.r[0] := x1;
  549.     v.r[1] := y1;
  550.     WinDials.WinDialDraw (tree, 0, 8, v.r, TRUE);
  551.   END redrawGrName;
  552.   
  553.   PROCEDURE selName(tree: mtUtils.tObjcTree; chInfo: changeInfoPtr);
  554.   BEGIN
  555.     (* Empf„nger ausw„hlen *)
  556.     v.bool := ListHelp.SelectName (chInfo^.grName);
  557.     IF v.bool
  558.     THEN
  559.       mtUtils.SetObjcString (tree, MausTauschrsc.chgrstr, msgAn);
  560.       mtUtils.SetObjcString (tree, MausTauschrsc.chgruppe, chInfo^.grName);
  561.       Strings.Assign (chInfo^.grName, chInfo^.lastName, v.bool);
  562.       chInfo^.isPrivate := TRUE;
  563.       redrawGrName(tree);
  564.     END;
  565.   END selName;
  566.   
  567.   PROCEDURE selGroup(tree: mtUtils.tObjcTree; chInfo: changeInfoPtr);
  568.     VAR newGroup : CARDINAL;
  569.   BEGIN
  570.     (* Gruppe ausw„hlen *)
  571.     v.bool := ListHelp.SelectGroup (chInfo^.grName, newGroup, TRUE, FALSE, FALSE, ListHelp.gsmWrite);
  572.     IF v.bool
  573.     THEN
  574.       mtUtils.SetObjcString (tree, MausTauschrsc.chgrstr, msgGroup);
  575.       IF newGroup # dataSys.private THEN 
  576.         mtUtils.SetObjcString (tree, MausTauschrsc.chgruppe, chInfo^.grName);
  577.       END;
  578.       Strings.Assign (chInfo^.grName, chInfo^.lastName, v.bool);
  579.       redrawGrName(tree);
  580.       chInfo^.isPrivate := FALSE;
  581.     END;
  582.   END selGroup;
  583.  
  584.   PROCEDURE DiscardRadioSelect(tree, popup1: mtUtils.tObjcTree; sel : INTEGER);
  585.     VAR t : Trick;
  586.   BEGIN
  587.     t := ADR (tree^[MausTauschrsc.chtype1].obState);
  588.     t^.hi := CHR(sel);
  589.     VDIUtil.SetXString (tree, MausTauschrsc.chtype1, popup1, sel);
  590.     WinDials.WinDialDraw (tree, MausTauschrsc.chtype1, 0, v.r, FALSE);
  591.   END DiscardRadioSelect;
  592.   
  593.   PROCEDURE enablePopup (tree: ADDRESS; ob : INTEGER; enable : BOOLEAN; draw : BOOLEAN);
  594.   BEGIN
  595.     mtUtils.SetFlag (tree, ob,    MagicAES.TOUCHEXIT, enable);
  596.     mtUtils.SetFlag (tree, ob+1,  MagicAES.TOUCHEXIT, enable);
  597.     mtUtils.SetState (tree, ob,   MagicAES.DISABLED, ~enable);
  598.     mtUtils.SetState (tree, ob+1, MagicAES.DISABLED, ~enable);
  599.     IF draw THEN
  600.       WinDials.WinDialDraw (tree, ob, 1, v.r, FALSE);
  601.     END;
  602.   END enablePopup;
  603.   
  604. PROCEDURE changeButton (obTree: ADDRESS; private: ADDRESS; button: INTEGER;
  605.                         mx, my : INTEGER; kstate: BITSET; clicks: INTEGER): BOOLEAN;
  606.   VAR chInfo    : changeInfoPtr;
  607.       but       : INTEGER;
  608.       popup1,
  609.       popup2,
  610.       pop       : ADDRESS;
  611.       x, y      : INTEGER;
  612.       max       : CARDINAL;
  613.       scrap     : CatTypes.String255;
  614.       t         : Trick;
  615.       tree      : mtUtils.tObjcTree;
  616. BEGIN
  617.   tree := obTree;
  618.   but := INTEGER(BITSET(button) - {15});
  619.   popup1 := MausTauschrsc.TreeAddr^[MausTauschrsc.msgtypbx];
  620.   popup2 := MausTauschrsc.TreeAddr^[MausTauschrsc.distribx];
  621.   chInfo := private;
  622.   WITH chInfo^ DO
  623.     IF but = MausTauschrsc.chdist0
  624.     THEN
  625.       but := MausTauschrsc.chdist1
  626.     ELSIF but = MausTauschrsc.chtype0
  627.     THEN
  628.       but := MausTauschrsc.chtype1
  629.     END;
  630.     mtUtils.ExclState (tree, but, MagicAES.SELECTED);
  631.     CASE but OF 
  632.       MausTauschrsc.chhelp  : CatHelp.DoHelp (CatHelp.changemsg);
  633.                               WinDials.WinDialDraw (tree, 0, 8, v.r, TRUE); |
  634.       MausTauschrsc.chquit  : RETURN TRUE; |
  635.       MausTauschrsc.chok    : mtUtils.ObjcString (tree, MausTauschrsc.chwegen, scrap);
  636.                               IF ~isCopy
  637.                               THEN
  638.                                 IF grinTools.CheckBetreff (scrap)
  639.                                 THEN
  640.                                   mtUtils.SetObjcString (tree, MausTauschrsc.chwegen, scrap);
  641.                                   RETURN TRUE;
  642.                                 END;
  643.                               ELSIF (LENGTH (scrap) > 79) & isCopy
  644.                               THEN
  645.                                 MTE.info (MTE.longCopy);
  646.                               ELSE
  647.                                 RETURN TRUE;
  648.                               END; 
  649.                               mtUtils.CalcArea (tree, but, v.r);
  650.                               WinDials.WinDialDraw (tree, 0, 8, v.r, TRUE); |
  651.       MausTauschrsc.chdist1,
  652.       MausTauschrsc.chtype1 : IF but = MausTauschrsc.chdist1
  653.                               THEN
  654.                                 pop := popup2
  655.                               ELSE
  656.                                 pop := popup1
  657.                               END;
  658.                               IF ~mtUtils.InState (tree, but, MagicAES.DISABLED)
  659.                               THEN
  660.                                 MagicAES.ObjcOffset (tree, but, x, y);
  661.                                 t := ADR (tree^[but].obState);
  662.                                 select := mtPopups.TreePopup (pop, x, y, ORD(t^.hi))-1;
  663.                                 IF select >= 0 THEN
  664.                                   t^.hi := CHR(select);
  665.                                   VDIUtil.SetXString (tree, but, pop, select);
  666.                                   WinDials.WinDialDraw (tree, but, 0, v.r, FALSE);
  667.                                 END; 
  668.                               END; |
  669.       MausTauschrsc.chdist2,
  670.       MausTauschrsc.chtype2 : IF but = MausTauschrsc.chdist2
  671.                               THEN
  672.                                 pop := popup2;
  673.                                 max := 4;
  674.                               ELSE
  675.                                 pop := popup1;
  676.                                 max := 2;
  677.                               END;
  678.                               t := ADR (tree^[but-1].obState);
  679.                               t^.hi := CHR((ORD(t^.hi)+1) MOD max);
  680.                               select := ORD (t^.hi);
  681.                               VDIUtil.SetXString (tree, but-1, pop, select);
  682.                               (*
  683.                               mtUtils.ObjcString (pop, select+1, selStr);
  684.                               mtUtils.SetObjcString (tree, but-1, selStr);
  685.                               *)
  686.                               WinDials.WinDialDraw (tree, but-1, 0, v.r, FALSE); |
  687.       MausTauschrsc.chgruppe: (* Entweder neuen Namen oder neue Gruppe ausw„hlen und setzen *)
  688.                               IF isPrivate
  689.                               THEN
  690.                                 mtUtils.ObjcString (tree, but, scrap);
  691.                                 selName(tree, chInfo);
  692.                               ELSE
  693.                                 selGroup(tree, chInfo);
  694.                               END; 
  695.                               redrawGrName(tree); |
  696.     ELSE
  697.     END;
  698.     IF (but = MausTauschrsc.chtype1) OR (but = MausTauschrsc.chtype2)
  699.     THEN
  700.       t := ADR (tree^[MausTauschrsc.chtype1].obState);
  701.       IF isPrivate & (t^.hi = 1C)
  702.       THEN
  703.         Strings.Assign ("", grName, v.bool);
  704.         selGroup(tree, chInfo);
  705.         IF ~v.bool
  706.         THEN
  707.           DiscardRadioSelect (tree, popup1, 0);
  708.         ELSE
  709.           enablePopup (tree, MausTauschrsc.chdist1, ~(isPrivate OR isCopy), TRUE);
  710.         END;
  711.       ELSIF ~isPrivate & (t^.hi = 0C)
  712.       THEN
  713.         Strings.Assign ("", grName, v.bool);
  714.         Strings.Assign ('',scrap, v.bool);
  715.         selName(tree, chInfo);
  716.         IF ~v.bool
  717.         THEN
  718.           DiscardRadioSelect (tree, popup1, 1);
  719.         ELSE
  720.           enablePopup (tree, MausTauschrsc.chdist1, ~(isPrivate OR isCopy), TRUE);
  721.         END;
  722.       END;
  723.     END;
  724.   END;
  725.   RETURN FALSE;
  726. END changeButton;
  727.  
  728. PROCEDURE changeGetSetValues (tree: ADDRESS; env: ADDRESS; 
  729.                               set: BOOLEAN; exit: INTEGER);
  730.   VAR chInfo    : changeInfoPtr;
  731.       popup1,
  732.       popup2,
  733.       pop       : ADDRESS;
  734.       max       : CARDINAL;
  735.       scrap     : CatTypes.String255;
  736. BEGIN
  737.   chInfo := env;
  738.   chInfo^.exitBut := INTEGER(BITSET(exit) - {15});
  739.   popup1 := MausTauschrsc.TreeAddr^[MausTauschrsc.msgtypbx];
  740.   popup2 := MausTauschrsc.TreeAddr^[MausTauschrsc.distribx];
  741.   IF set
  742.   THEN
  743.     WITH chInfo^ DO
  744.       mtUtils.SetState (tree, MausTauschrsc.chklemm, MagicAES.SELECTED, ~msg.sendMsg);
  745.       isPrivate := (msg.msgType = answer) OR (msg.msgType = private) OR (msg.msgType = persanswer);
  746.       isCopy := (msg.msgType = copyOwn) OR (msg.msgType = copyOther) OR (msg.msgType = forward);
  747.       isPrivate := isPrivate OR isCopy;
  748.       IF isPrivate
  749.       THEN
  750.         max := 0;
  751.       ELSE
  752.         max := 1;
  753.       END;
  754.       IF (msg.refId # NIL) & (LENGTH (msg.refId^) > 0)
  755.       THEN
  756.         mtUtils.SetObjcString (tree, MausTauschrsc.chrefid, msg.refId^);
  757.       ELSE
  758.         mtUtils.SetObjcString (tree, MausTauschrsc.chrefid, "");
  759.       END;
  760.       VDIUtil.SetXState (tree, MausTauschrsc.chtype1, max);
  761.       VDIUtil.SetXString (tree, MausTauschrsc.chtype1, popup1, max);
  762.       enablePopup (tree, MausTauschrsc.chtype1, ~isCopy, FALSE);
  763.       IF isPrivate 
  764.       THEN
  765.         mtUtils.SetObjcString (tree, MausTauschrsc.chgrstr, msgAn);
  766.         mtUtils.SetObjcString (tree, MausTauschrsc.chgruppe, msg.receiver^);
  767.         Strings.Assign (msg.receiver^, lastName, v.bool);
  768.         Strings.Assign (msg.receiver^, grName, v.bool);
  769.       ELSE
  770.         mtUtils.SetObjcString (tree, MausTauschrsc.chgrstr, msgGroup);
  771.         mtUtils.SetObjcString (tree, MausTauschrsc.chgruppe, msg.group^);
  772.         Strings.Assign (msg.group^, lastName, v.bool);
  773.         Strings.Assign (msg.group^, grName, v.bool);
  774.       END;
  775.  
  776.       mtUtils.SetObjcString (tree, MausTauschrsc.chwegen, msg.topic^);
  777.       VDIUtil.SetXState (tree, MausTauschrsc.chdist1, ORD (msg.dist));
  778.       VDIUtil.SetXString (tree, MausTauschrsc.chdist1, popup2, ORD(msg.dist));
  779.       enablePopup (tree, MausTauschrsc.chdist1, ~(isPrivate OR isCopy), FALSE);
  780.       
  781.       wasPrivate := isPrivate;
  782.     END;
  783.   ELSE
  784.     WITH chInfo^ DO
  785.       IF exitBut = MausTauschrsc.chok
  786.       THEN
  787.         msg.dist := data.tDistribution(VDIUtil.GetXState (tree, MausTauschrsc.chdist1));
  788.         msg.sendMsg := ~mtUtils.InState (tree, MausTauschrsc.chklemm, MagicAES.SELECTED);
  789.         mtUtils.ObjcString (tree, MausTauschrsc.chwegen, scrap);
  790.         IF ~Strings.StrEqual (msg.topic^, scrap) 
  791.          & (LENGTH (scrap) > LENGTH (msg.topic^))
  792.         THEN
  793.           DEALLOCATE (msg.topic, 0);
  794.           ALLOCATE (msg.topic, LENGTH (scrap)+2);
  795.         END;
  796.         Strings.Assign (scrap, msg.topic^, v.bool);
  797.         (*
  798.         mtUtils.ObjcString (tree, MausTauschrsc.chgruppe, scrap);
  799.         *)
  800.         (* lastName enth„lt den zuletzt ausgew„hlten Namen oder die
  801.          * zuletzt ausgew„hlte Gruppe
  802.          *)
  803.         Strings.Assign (lastName, scrap, v.bool);
  804.         IF isPrivate
  805.         THEN
  806.           IF ~Strings.StrEqual (msg.receiver^, scrap)
  807.           THEN
  808.             IF msg.msgType = answer
  809.             THEN
  810.               (* war Antwort, wird zu L„stermail *)
  811.               msg.msgType := persanswer;
  812.               msg.noRefLine := TRUE;
  813.             END;
  814.             IF (LENGTH (scrap) > LENGTH (msg.receiver^))
  815.             THEN
  816.               DEALLOCATE (msg.receiver, 0);
  817.               ALLOCATE (msg.receiver, LENGTH (scrap)+2);
  818.             END;
  819.           END;
  820.           Strings.Assign (scrap, msg.receiver^, v.bool);
  821.           IF ~wasPrivate
  822.           THEN
  823.             IF ((msg.msgType = comment) OR (msg.msgType = groupcomment)) & (msg.refId # NIL) & (msg.refId^[0] # 0C) 
  824.             THEN
  825.               msg.msgType := persanswer;
  826.               msg.noRefLine := TRUE;
  827.             ELSE
  828.               msg.msgType := private
  829.             END;
  830.           END;
  831.         ELSE
  832.           IF ~Strings.StrEqual (msg.group^, scrap) 
  833.            & (LENGTH (scrap) > LENGTH (msg.group^))
  834.           THEN
  835.             DEALLOCATE (msg.group, 0);
  836.             ALLOCATE (msg.group, LENGTH (scrap)+2);
  837.           END;
  838.           Strings.Assign (scrap, msg.group^, v.bool);
  839.           IF wasPrivate
  840.           THEN
  841.             IF ((msg.msgType = private) OR (msg.msgType = persanswer)) & (msg.refId # NIL) & (msg.refId^[0] # 0C) 
  842.             THEN
  843.               IF Strings.StrEqual (msg.group^, msg.orgGroup^)
  844.               THEN
  845.                 msg.msgType := comment;
  846.                 msg.noRefLine := FALSE;
  847.               ELSE
  848.                 msg.msgType := groupcomment
  849.               END;
  850.             ELSE
  851.               msg.msgType := mail
  852.             END;
  853.           ELSE
  854.             IF ~Strings.StrEqual (msg.group^, msg.orgGroup^) & (msg.msgType = comment)
  855.             THEN
  856.               msg.msgType := groupcomment
  857.             ELSIF Strings.StrEqual (msg.group^, msg.orgGroup^) & (msg.msgType = groupcomment)
  858.             THEN
  859.               msg.msgType := comment;
  860.               msg.noRefLine := FALSE;
  861.             END;
  862.           END;
  863.         END;
  864.         Messages.WriteHdrInfo (msg);
  865.       END;
  866.     END;
  867.   END;
  868. END changeGetSetValues;
  869.  
  870. PROCEDURE changeHdr (VAR message : Messages.msgInfo): BOOLEAN;
  871.   VAR tree : mtUtils.tObjcTree;
  872.       cInfo     : changeInfoPtr;
  873.       but       : INTEGER;  
  874. BEGIN 
  875.   tree := MausTauschrsc.TreeAddr^[MausTauschrsc.changebx];
  876.   NEW (cInfo);
  877.   IF cInfo = NIL 
  878.   THEN
  879.     MTE.noMemAlert();
  880.     RETURN FALSE
  881.   END;
  882.   cInfo^.msg := message;
  883.   Strings.Assign ("", cInfo^.grName, v.bool);
  884.   IF WinDials.OpenWinDial (tree, TRUE,
  885.                            changeGetSetValues,
  886.                            changeGetSetValues,
  887.                            changeButton,
  888.                            WinDials.defDraw,
  889.                            "",
  890.                            cInfo)
  891.   
  892.   THEN
  893.     WinDials.WinDialHandleEvents();
  894.     
  895.     but := cInfo^.exitBut;
  896.     IF but = MausTauschrsc.chok
  897.     THEN
  898.       message := cInfo^.msg;
  899.     END;
  900.   ELSE
  901.     MTE.info (MTE.NoWinDial);
  902.     but := -1;
  903.   END;
  904.   DISPOSE (cInfo);
  905.   RETURN but = MausTauschrsc.chok;
  906. END changeHdr;
  907.  
  908. PROCEDURE careForButtons(ptr : msgWdwPtr; redraw : BOOLEAN);
  909.   VAR selectCount : INTEGER;
  910.       msg       : Messages.msgInfo;
  911.       rdwCount,
  912.       i         : INTEGER;
  913.       isComm,
  914.       isMail    : BOOLEAN;
  915.       selSet,
  916.       disSet    : BITSET;
  917. BEGIN
  918.   WITH ptr^ DO
  919.     selSet := {};
  920.     disSet := {};
  921.     FOR i := MausTauschrsc.ctrledit TO MausTauschrsc.ctrldis2 DO
  922.       IF mtUtils.InState (butBox, i, MagicAES.SELECTED) THEN INCL (selSet, i); END;
  923.       IF mtUtils.InState (butBox, i, MagicAES.DISABLED) THEN INCL (disSet, i); END;
  924.     END;
  925.     INCL (selSet, MausTauschrsc.ctrldis1);  (* Fr Redraw *)
  926.     IF (wdw > 0) & hasSelectedEntries (ptr, sel)
  927.     THEN
  928.       selectCount := countSelectedEntries (ptr);
  929.       msg := Messages.msgArray^[sel];
  930.       mtUtils.SetState (butBox, MausTauschrsc.ctrldel, MagicAES.DISABLED, FALSE);
  931.       IF selectCount = 1
  932.       THEN
  933.         isMail := (msg.msgType = mail) OR (msg.msgType = comment) OR (msg.msgType = groupcomment);
  934.         isComm := ~((msg.msgType=mail) OR (msg.msgType = private));
  935.         mtUtils.SetState (butBox, MausTauschrsc.ctrledit, MagicAES.DISABLED, 
  936.                          (msg.msgType = copyOwn) OR (msg.msgType = copyOther) OR (msg.msgType = forward)); 
  937.         mtUtils.SetState (butBox, MausTauschrsc.ctrlview, MagicAES.DISABLED, 
  938.                          (msg.msgType = copyOwn) OR (msg.msgType = copyOther) OR (msg.msgType = forward)); 
  939.         mtUtils.SetState (butBox, MausTauschrsc.ctrlkomm, MagicAES.DISABLED,
  940.                           ~isMail); 
  941.         mtUtils.SetState (butBox, MausTauschrsc.ctrlcopy, MagicAES.DISABLED,
  942.                           ~((msg.msgType = private) OR (msg.msgType = answer) OR (msg.msgType = persanswer)) ); 
  943.         mtUtils.SetState (butBox, MausTauschrsc.ctrlhdr, MagicAES.DISABLED, FALSE);
  944.         mtUtils.SetState (butBox, MausTauschrsc.ctrlback, MagicAES.DISABLED, ~isComm);
  945.   
  946.         mtUtils.SetState (butBox, MausTauschrsc.ctrldis1, MagicAES.DISABLED, ~isMail);
  947.         mtUtils.SetState (butBox, MausTauschrsc.ctrldis2, MagicAES.DISABLED, ~isMail);
  948.         VDIUtil.SetXState  (butBox, MausTauschrsc.ctrldis1, ORD(Messages.msgArray^[sel].dist));
  949.         VDIUtil.SetXString (butBox, MausTauschrsc.ctrldis1, distSel, ORD(Messages.msgArray^[sel].dist));
  950.         INCL (selSet, MausTauschrsc.ctrldis1);  (* Fr Redraw *)
  951.         (*
  952.         FOR i := MausTauschrsc.ctrlnone TO MausTauschrsc.ctrl_net DO
  953.           mtUtils.SetState (butBox, i, MagicAES.SELECTED, FALSE);
  954.           mtUtils.SetState (butBox, i, MagicAES.DISABLED, ~isMail);
  955.         END;
  956.         mtUtils.SetState (butBox, MausTauschrsc.ctrlnone + ORD (Messages.msgArray^[sel].dist), MagicAES.SELECTED, isMail);
  957.         *)
  958.       ELSE
  959.         mtUtils.SetState (butBox, MausTauschrsc.ctrledit, MagicAES.DISABLED, FALSE);
  960.         mtUtils.SetState (butBox, MausTauschrsc.ctrlkomm, MagicAES.DISABLED, TRUE);
  961.         mtUtils.SetState (butBox, MausTauschrsc.ctrlview, MagicAES.DISABLED, FALSE);
  962.         mtUtils.SetState (butBox, MausTauschrsc.ctrlcopy, MagicAES.DISABLED, TRUE);
  963.         mtUtils.SetState (butBox, MausTauschrsc.ctrlhdr, MagicAES.DISABLED,  TRUE);
  964.         mtUtils.SetState (butBox, MausTauschrsc.ctrlback, MagicAES.DISABLED, TRUE);
  965.         mtUtils.SetState (butBox, MausTauschrsc.ctrldis1, MagicAES.DISABLED, TRUE);
  966.         mtUtils.SetState (butBox, MausTauschrsc.ctrldis2, MagicAES.DISABLED, TRUE);
  967.         VDIUtil.SetXString (butBox, MausTauschrsc.ctrldis1, distSel, 0);
  968.         (*
  969.         FOR i := MausTauschrsc.ctrlnone TO MausTauschrsc.ctrl_net DO
  970.           mtUtils.SetState (butBox, i, MagicAES.SELECTED, FALSE);
  971.           mtUtils.SetState (butBox, i, MagicAES.DISABLED, TRUE);
  972.         END;
  973.         *)
  974.       END;  
  975.     ELSE
  976.       FOR i := MausTauschrsc.ctrledit TO MausTauschrsc.ctrldis2 DO
  977.         mtUtils.ExclState (butBox, i, MagicAES.SELECTED);
  978.         mtUtils.InclState (butBox, i, MagicAES.DISABLED);
  979.       END;
  980.       mtUtils.ExclState (butBox, MausTauschrsc.ctrldis0, MagicAES.DISABLED);
  981.       VDIUtil.SetXString (butBox, MausTauschrsc.ctrldis1, distSel, 0);
  982.     END;
  983.     (* Alle neuzeichnen *)
  984.     IF redraw & (wdw >= 0) THEN 
  985.       rdwCount := 0;
  986.       FOR i := MausTauschrsc.ctrledit TO MausTauschrsc.ctrldis2 DO
  987.         IF (mtUtils.InState (butBox, i, MagicAES.SELECTED) # (i IN selSet)) OR 
  988.            (mtUtils.InState (butBox, i, MagicAES.DISABLED) # (i IN disSet))
  989.         THEN
  990.           INC (rdwCount); 
  991.         END;
  992.       END;
  993.       IF rdwCount < 5
  994.       THEN
  995.         FOR i := MausTauschrsc.ctrledit TO MausTauschrsc.ctrldis2 DO
  996.           IF (mtUtils.InState (butBox, i, MagicAES.SELECTED) # (i IN selSet)) OR 
  997.              (mtUtils.InState (butBox, i, MagicAES.DISABLED) # (i IN disSet))
  998.           THEN
  999.             redrawButton (wdw, butBox, i); 
  1000.           END;
  1001.         END;
  1002.       ELSE
  1003.         redrawButton (wdw, butBox, 0); 
  1004.       END;
  1005.     END;
  1006.   END;
  1007. END careForButtons;
  1008.  
  1009. PROCEDURE openSelected(ptr : msgWdwPtr; forView: BOOLEAN);
  1010.   VAR i : INTEGER;
  1011. BEGIN
  1012.   IF hasSelectedEntries (ptr, v.int)
  1013.   THEN
  1014.     FOR i := 0 TO ptr^.maxPos DO 
  1015.       IF ptr^.list^[i].selected
  1016.       THEN
  1017.         Messages.OpenEditor (ptr^.list^[i], FALSE, -1, 0, forView);
  1018.       END;
  1019.     END;
  1020.   END;
  1021. END openSelected;
  1022.  
  1023. PROCEDURE handleButtons (ptr : msgWdwPtr; ob : INTEGER) : BOOLEAN;
  1024.   VAR i      : INTEGER;
  1025.       oldDist: INTEGER;
  1026.       selectCount : INTEGER;
  1027.       msg    : Messages.msgInfo;
  1028.       name,
  1029.       Betreff,
  1030.       msgName: CatTypes.String255;
  1031.       x, y   : INTEGER;
  1032.       select : INTEGER;
  1033.       t      : Trick;
  1034.  
  1035.   PROCEDURE handleSelChanged(redrawBut: BOOLEAN);
  1036.   BEGIN
  1037.     WITH ptr^ DO
  1038.       Messages.WriteMessageInfo(FALSE);
  1039.       redrawEntry (sel);
  1040.       IF redrawBut THEN careForButtons (ptr, TRUE); END;
  1041.       (* Jetzt nachsehen, ob das irgendwo benutzt wird, und 
  1042.        * dann auch dort die Anzeige „ndern 
  1043.        *)
  1044.       Messages.UpdateEditors (Messages.msgArray^[sel]);
  1045.     END;
  1046.   END handleSelChanged;
  1047.  
  1048. BEGIN
  1049.   WITH ptr^ DO
  1050.     IF ~mtUtils.InState (butBox, ob, MagicAES.DISABLED)
  1051.       & (mtUtils.InFlag (butBox, ob, MagicAES.SELECTABLE)
  1052.          OR (ob = MausTauschrsc.ctrldis2))
  1053.     THEN
  1054.       (* Button selektieren *)
  1055.       IF ob # MausTauschrsc.ctrldis2
  1056.       THEN
  1057.         mtUtils.InclState (butBox, ob, MagicAES.SELECTED);
  1058.         redrawButton (wdw, butBox, ob);
  1059.       END;
  1060.       mtUtils.Bounce();
  1061.       (* Selektierte Nachrichten z„hlen *)
  1062.       selectCount := countSelectedEntries(ptr);
  1063.       IF selectCount = 1
  1064.       THEN
  1065.         v.bool := hasSelectedEntries (ptr, sel);
  1066.         msg := Messages.msgArray^[sel];
  1067.       END;
  1068.       CASE ob OF 
  1069.         MausTauschrsc.ctrledit : openSelected(ptr, FALSE); |
  1070.         MausTauschrsc.ctrlkomm : 
  1071.           IF (selectCount = 1) & 
  1072.              ((msg.msgType = mail) OR  
  1073.               (msg.msgType = comment) OR
  1074.               (msg.msgType = groupcomment))
  1075.           THEN
  1076.             IF ~msg.hdrRead
  1077.             THEN
  1078.               Messages.ReadHdrInfo (msg, TRUE);
  1079.             END;
  1080.             IF msg.hdrRead THEN
  1081.               IF msg.topic # NIL 
  1082.               THEN
  1083.                 Strings.Assign (msg.topic^, Betreff, v.bool);
  1084.               ELSE
  1085.                 Betreff := "";
  1086.               END;
  1087.               Messages.Number2Name (msg.number, msgName);
  1088.               IF grinTools.BetreffHolen(-1, Betreff, 'Stichwort fr Kommentar auf Nachricht :',
  1089.                                         msgName, msgWegen, FALSE) 
  1090.               THEN
  1091.                 Messages.MakeMausId (msg, msgName);
  1092.                 v.bool := Messages.CreateMessage (msg.number, '', msg.group^, msg.group^, msgName, Betreff, '', comment, 0, '', '', msg.dist, TRUE, v.int);
  1093.               END;
  1094.             END;
  1095.           END; |
  1096.         MausTauschrsc.ctrlview : openSelected(ptr, TRUE); |
  1097.         MausTauschrsc.ctrldel  : 
  1098.           IF selectCount > 0 
  1099.           THEN
  1100.             v.int := mtAlerts.Alert (2, MTE.delSelectedAlt);
  1101.             IF v.int = 1
  1102.             THEN
  1103.               i := Messages.messages-1;
  1104.               WHILE i >= 0 DO
  1105.                 IF list^[i].selected
  1106.                 THEN
  1107.                   Messages.Number2Name (list^[i].number, msgName);
  1108.                   Messages.deleteMessage (msgName, TRUE, TRUE);
  1109.                 END;
  1110.                 DEC (i);
  1111.                 (* i := BinOps.LowerInt (i, Messages.messages-1); *)
  1112.               END;
  1113.               sel := -1;
  1114.             END;
  1115.             careForButtons(ptr, TRUE);
  1116.           END; |
  1117.         MausTauschrsc.ctrlcopy : 
  1118.           IF (selectCount = 1) & 
  1119.              ((msg.msgType = answer) OR  
  1120.               (msg.msgType = persanswer) OR  
  1121.               (msg.msgType = private))
  1122.           THEN
  1123.             IF ~msg.hdrRead
  1124.             THEN
  1125.               Messages.ReadHdrInfo (msg, TRUE);
  1126.               IF ~msg.hdrRead THEN RETURN TRUE END;
  1127.             END;
  1128.             Strings.Assign ('', name, v.bool);
  1129.             IF msg.copyCount >= 10
  1130.             THEN
  1131.               MTE.info (MTE.maxCopyAlert);
  1132.             ELSE
  1133.               IF grinTools.GetCommentLine(Betreff, TRUE) & ListHelp.SelectName(name) THEN
  1134.                 Messages.Number2Name (msg.number, msgName);
  1135.                 Messages.CopyOwnMessage (msgName, name, '', Betreff, 1);
  1136.               END
  1137.             END;
  1138.           END; |
  1139.         MausTauschrsc.ctrlhdr  : 
  1140.           IF (selectCount = 1) 
  1141.           THEN
  1142.             IF ~Messages.msgArray^[sel].hdrRead
  1143.             THEN
  1144.               Messages.ReadHdrInfo (Messages.msgArray^[sel], FALSE);
  1145.             END;
  1146.             IF Messages.msgArray^[sel].hdrRead
  1147.                & changeHdr (Messages.msgArray^[sel])
  1148.             THEN
  1149.               handleSelChanged(TRUE);
  1150.             END;
  1151.           END; |
  1152.         MausTauschrsc.ctrlback : 
  1153.           IF (selectCount = 1)
  1154.           THEN
  1155.             Messages.openReference (sel);
  1156.           END; |
  1157.         MausTauschrsc.ctrldis1 :
  1158.           IF (selectCount = 1)
  1159.           THEN
  1160.             MagicAES.ObjcOffset (butBox, ob, x, y);
  1161.             t := ADR (butBox^[ob].obState);
  1162.             select := mtPopups.TreePopup (distSel, x, y, ORD(t^.hi))-1;
  1163.             IF select >= 0 THEN
  1164.               t^.hi := CHR(select);
  1165.               Messages.msgArray^[sel].dist := data.tDistribution (ORD (select));
  1166.               VDIUtil.SetXString (butBox, ob, distSel, select);
  1167.               (*
  1168.               redrawButton (ptr^.wdw, butBox, ob);
  1169.               *)
  1170.               handleSelChanged(FALSE);
  1171.             END;
  1172.           END; |
  1173.         MausTauschrsc.ctrldis2 : 
  1174.           IF (selectCount = 1)
  1175.           THEN
  1176.             mtUtils.ExclState (butBox, ob, MagicAES.SELECTED);
  1177.             DEC (ob);   (* Button nehmen *)
  1178.             t := ADR (butBox^[ob].obState);
  1179.             t^.hi := CHR((ORD(t^.hi)+1) MOD 4);
  1180.             select := ORD (t^.hi);
  1181.             Messages.msgArray^[sel].dist := data.tDistribution (ORD (select));
  1182.             VDIUtil.SetXString (butBox, ob, distSel, select);
  1183.             (* 
  1184.             redrawButton (ptr^.wdw, butBox, ob-1);
  1185.             *)
  1186.             handleSelChanged(FALSE);
  1187.           END;
  1188.       ELSE
  1189.       END;
  1190.       (* Button deselektieren *)
  1191.       mtUtils.ExclState (butBox, ob, MagicAES.SELECTED);
  1192.       redrawButton (ptr^.wdw, butBox, ob);
  1193.       RETURN TRUE
  1194.     ELSE
  1195.       RETURN FALSE;
  1196.     END;
  1197.   END;
  1198. END handleButtons;
  1199.  
  1200. PROCEDURE clickInMsgWindow(win, vdiH : INTEGER; special : ADDRESS; 
  1201.                            x,y : INTEGER; kstate, buts : BITSET; clicks : INTEGER): BOOLEAN;
  1202.   VAR transY : INTEGER;
  1203.       ptr    : msgWdwPtr;
  1204.       entrySelected : BOOLEAN;
  1205.       line   : INTEGER;
  1206.       but    : BITSET;
  1207.       i      : INTEGER;
  1208.       ob     : INTEGER;
  1209.       selectCount : INTEGER;
  1210.       msg    : Messages.msgInfo;
  1211.       name,
  1212.       Betreff,
  1213.       msgName: CatTypes.String255;
  1214.  
  1215.     PROCEDURE selectArea;
  1216.       VAR firstLine,
  1217.           lastLine : INTEGER;
  1218.           i        : INTEGER;
  1219.           r, 
  1220.           rect     : GrafBase.Rectangle;
  1221.           first    : BOOLEAN;
  1222.     BEGIN
  1223.       WITH ptr^ DO
  1224.         rect := GrafBase.Rectangle{x, y, 0, 0};
  1225.         mtAppl.MouseFinger ();
  1226.         MagicAES.GrafRubberbox (x, y, -32767, -32767, rect.w, rect.h);
  1227.         mtAppl.MouseArrow();
  1228.         
  1229.         WITH rect DO
  1230.           IF w < 0
  1231.           THEN
  1232.             INC(x, w);
  1233.             w := -w
  1234.           END;
  1235.           IF h < 0
  1236.           THEN
  1237.             INC (y, h);
  1238.             h := -h
  1239.           END;
  1240.         END;
  1241.         (* clippen *)
  1242.         rect := RectFuncs.ClipRect (rect, msgWork);
  1243.         rect.h := BinOps.LowerInt (rect.h, msgWork.y + msgWork.h - 1 - rect.y);
  1244.         
  1245.         (* Jetzt testen, ob selektierbarer Bereich geschnitten wurde *)
  1246.         IF (((rect.x - msgWork.x) < pixOffset) & ((rect.x + rect.w - msgWork.x) < pixOffset)) OR
  1247.            (((rect.x - msgWork.x) > maxWidth) & ((rect.x + rect.w - msgWork.x) > maxWidth))
  1248.         THEN
  1249.           RETURN
  1250.         END;
  1251.  
  1252.         firstLine := (rect.y - msgWork.y) DIV (2*charHeight + lineDist);
  1253.         lastLine  := (rect.y + rect.h - msgWork.y) DIV (2*charHeight + lineDist);
  1254.         IF (rect.x - msgWork.x > pixOffset) OR (rect.x + rect.w - msgWork.x > pixOffset)
  1255.         THEN
  1256.           r := msgWork;
  1257.           INC (r.x, pixOffset);
  1258.           r.h := 2*charHeight + lineDist;
  1259.           first := TRUE;
  1260.           FOR i := startPos+firstLine TO startPos+lastLine DO
  1261.             IF (i>= 0) & (i<= maxPos)
  1262.             THEN
  1263.               list^[i].selected := ~list^[i].selected;
  1264.               IF (i >= startPos) & (i <= startPos + windLines)
  1265.               THEN 
  1266.                 (* redraw *)
  1267.                 IF first THEN 
  1268.                   r.y := msgWork.y + INTEGER(i - startPos) * (2*charHeight+lineDist);
  1269.                   first := FALSE
  1270.                 ELSE
  1271.                   r.h := msgWork.y + INTEGER(i - startPos + 1) * (2*charHeight+lineDist) - r.y;
  1272.                 END;
  1273.               END;
  1274.             END;
  1275.           END;
  1276.           IF ~first THEN WdwManager.RedrawWdw (wdw, r) END;
  1277.         END;
  1278.       END;
  1279.     END selectArea;
  1280.  
  1281. BEGIN
  1282.   ptr := msgWdwPtr (special);
  1283.   WITH ptr^ DO
  1284.     IF ~(0 IN buts) THEN RETURN FALSE END;
  1285.     IF RectFuncs.IsInRect (x, y, butWork)
  1286.     THEN
  1287.       ob := MagicAES.ObjcFind (butBox,  0, 8, x, y);
  1288.       IF (ob >= MausTauschrsc.ctrledit) & (ob <= MausTauschrsc.ctrldis2)
  1289.       THEN
  1290.         RETURN handleButtons (ptr, ob);
  1291.       END;
  1292.     ELSIF RectFuncs.IsInRect (x, y, msgWork)
  1293.     THEN
  1294.       IF ~((MagicAES.KRSHIFT IN kstate) OR (MagicAES.KLSHIFT IN kstate))
  1295.       THEN
  1296.         deselectEntries (ptr);
  1297.         sel := -1;
  1298.       END;
  1299.       (* Zeile herausfinden *)
  1300.       line := (y - msgWork.y) DIV (2*charHeight + lineDist);
  1301.       transY := (y - msgWork.y - (lineDist DIV 2));
  1302.       entrySelected := (transY >= line*(2*charHeight + lineDist)) & 
  1303.                        (transY < ((line+1) * 2*charHeight + line*lineDist)) &
  1304.                        ((x - msgWork.x) >= pixOffset) &
  1305.                        ((x - msgWork.x) <= maxWidth) &
  1306.                        (line+startPos <= maxPos);
  1307.       IF entrySelected
  1308.       THEN
  1309.         toggleEntry (ptr, line+startPos);
  1310.         IF list^[line+startPos].selected THEN
  1311.           sel := line+startPos;
  1312.         ELSE
  1313.           sel := -1;
  1314.         END;
  1315.         IF clicks > 1
  1316.         THEN
  1317.           openSelected(ptr, FALSE);
  1318.         ELSE
  1319.           REPEAT 
  1320.             MagicAES.GrafMkstate (x, y, but, kstate);
  1321.           UNTIL ~(0 IN but);
  1322.         END;
  1323.       ELSE
  1324.         MagicAES.GrafMkstate (x, y, but, kstate);
  1325.         IF 0 IN but
  1326.         THEN
  1327.           (* Graf-Rubberbox aufrufen *)
  1328.           selectArea();
  1329.         END;
  1330.       END;
  1331.       careForButtons (ptr, TRUE);
  1332.       RETURN TRUE;
  1333.     END;
  1334.   END;
  1335.   RETURN FALSE;
  1336. END clickInMsgWindow;
  1337.  
  1338. PROCEDURE handleMsgKey (wdw, vdiH : INTEGER; special : ADDRESS; taste: INTEGER; char, scan : CHAR; kstate : BITSET) : BOOLEAN;
  1339.   VAR ptr   : msgWdwPtr;
  1340.       gemCh : CARDINAL;
  1341.       key   : MOSGlobals.Key;
  1342.       ctrl  : BOOLEAN;
  1343.       done  : BOOLEAN;
  1344.       doc   : GrafBase.LongRect;
  1345.       newPos: BOOLEAN;
  1346.       pg    : BOOLEAN;
  1347.   
  1348.   PROCEDURE deselectLast();
  1349.   BEGIN
  1350.     IF countSelectedEntries (ptr) > 1
  1351.     THEN
  1352.       deselectEntries (ptr);
  1353.     ELSE
  1354.       toggleEntry (ptr, ptr^.sel);
  1355.     END;
  1356.   END deselectLast;
  1357.   
  1358. BEGIN
  1359.   ptr := msgWdwPtr (special);
  1360.   WITH ptr^ DO
  1361.     gemCh := ORD(scan) * 256 + ORD(char);
  1362.     Keyboard.GemCharToKey (gemCh,  SHORT (INTEGER(kstate)), key);
  1363.     ctrl := MagicAES.KCTRL IN kstate;
  1364.     done := TRUE;
  1365.     newPos := FALSE;
  1366.     IF Keyboard.IsSpecial (key)
  1367.     THEN
  1368.       CASE Keyboard.SpecialKey (key) OF
  1369.         left          : WdwManager.ScrollLeft (wdw, 1);  |
  1370.         soln          : WdwManager.PageLeft (wdw);    |
  1371.         right         : WdwManager.ScrollRight (wdw, 1); | 
  1372.         eoln          : WdwManager.PageRight (wdw);   |
  1373.         pgUp,
  1374.         up            : pg := Keyboard.SpecialKey (key) = pgUp;
  1375.                         IF pg THEN WdwManager.PageUp (wdw); END;
  1376.                         IF sel = -1 
  1377.                         THEN
  1378.                           sel := BinOps.LowerInt (maxPos, startPos+windLines-1);
  1379.                           toggleEntry (ptr, sel);
  1380.                         ELSIF sel > 0 THEN 
  1381.                           deselectLast();
  1382.                           IF pg THEN 
  1383.                             DEC (sel, windLines-1);
  1384.                             sel := BinOps.HigherInt (0, sel);
  1385.                           ELSE
  1386.                             DEC (sel); 
  1387.                           END;
  1388.                           sel := BinOps.LowerInt (sel, maxPos);
  1389.                           toggleEntry (ptr, sel);
  1390.                           IF (sel < startPos) OR (sel > startPos + windLines-1)
  1391.                           THEN
  1392.                             startPos := BinOps.LowerInt (maxPos - windLines+1, sel);
  1393.                             newPos := TRUE;
  1394.                           END; 
  1395.                         END; |
  1396.         pgDown,
  1397.         down          : pg := Keyboard.SpecialKey (key) = pgDown;
  1398.                         IF pg THEN WdwManager.PageDown (wdw); END;  
  1399.                         IF sel = -1
  1400.                         THEN
  1401.                           sel := startPos;
  1402.                           toggleEntry (ptr, sel);
  1403.                         ELSIF sel < maxPos THEN 
  1404.                           deselectLast();
  1405.                           IF pg THEN
  1406.                             INC (sel, windLines-1);
  1407.                             sel := BinOps.LowerInt (sel, maxPos);
  1408.                           ELSE
  1409.                             INC (sel); 
  1410.                           END;
  1411.                           sel := BinOps.HigherInt (sel, 0);
  1412.                           toggleEntry (ptr, sel);
  1413.                           IF (sel < startPos) OR (sel > startPos + windLines-1)
  1414.                           THEN
  1415.                             startPos := BinOps.LowerInt (maxPos - windLines+1, sel-windLines+1);
  1416.                             newPos := TRUE;
  1417.                           END; 
  1418.                         END; 
  1419.                         |
  1420.         home,
  1421.         clr           : IF sel >= 0 THEN 
  1422.                           deselectLast();
  1423.                           pg := TRUE;
  1424.                         ELSE
  1425.                           pg := FALSE;
  1426.                         END;
  1427.                         IF Keyboard.SpecialKey (key) = home
  1428.                         THEN
  1429.                           sel := 0;
  1430.                           IF pg THEN toggleEntry (ptr, sel); END;
  1431.                           startPos := 0;
  1432.                         ELSE
  1433.                           sel := maxPos;
  1434.                           IF pg THEN toggleEntry (ptr, sel); END;
  1435.                           startPos := BinOps.HigherInt (maxPos - windLines+1, 0);
  1436.                         END; 
  1437.                         IF ~pg 
  1438.                         THEN
  1439.                           sel := -1;
  1440.                         END;
  1441.                         newPos := TRUE;
  1442.                         |
  1443.         return,
  1444.         enter         : openSelected (ptr, FALSE); |
  1445.         esc           : deselectEntries (ptr); sel := -1; |
  1446.       ELSE
  1447.         done := FALSE
  1448.       END;
  1449.       IF newPos 
  1450.       THEN
  1451.         startPos := BinOps.HigherInt (0, startPos);
  1452.         WdwManager.SetWdwDocument (wdw, GrafBase.LongRect{LONG(leftOffset), startPos, LONG(maxWidth), maxPos});
  1453.       END;
  1454.       careForButtons (ptr, TRUE);
  1455.     ELSIF ~ctrl & ~CatGlobal.WithAlt (kstate)
  1456.     THEN
  1457.       CASE CAP (char) OF
  1458.         'A' : RETURN handleButtons (ptr, MausTauschrsc.ctrlhdr);  |
  1459.         'C' : RETURN handleButtons (ptr, MausTauschrsc.ctrlcopy); |
  1460.         'E' : RETURN handleButtons (ptr, MausTauschrsc.ctrledit); |
  1461.         'K' : RETURN handleButtons (ptr, MausTauschrsc.ctrlkomm); |
  1462.         'L' : RETURN handleButtons (ptr, MausTauschrsc.ctrldel);  |
  1463.         'O' : RETURN handleButtons (ptr, MausTauschrsc.ctrlback); |
  1464.         'D' : IF CatGlobal.WithShift (kstate)
  1465.               THEN
  1466.                 RETURN handleButtons (ptr, MausTauschrsc.ctrldis2);
  1467.               ELSE
  1468.                 RETURN handleButtons (ptr, MausTauschrsc.ctrldis1);
  1469.               END; |
  1470.         'V' : RETURN handleButtons (ptr, MausTauschrsc.ctrlview); |
  1471.         (*
  1472.         '0' : RETURN handleButtons (ptr, MausTauschrsc.ctrlnone); |
  1473.         '1' : RETURN handleButtons (ptr, MausTauschrsc.ctllokal); |
  1474.         '2' : RETURN handleButtons (ptr, MausTauschrsc.ctrlmaus); |
  1475.         '3' : RETURN handleButtons (ptr, MausTauschrsc.ctrl_net); |
  1476.         *)
  1477.       ELSE
  1478.         done := FALSE;
  1479.       END;
  1480.     ELSE
  1481.       done := FALSE
  1482.     END;
  1483.     RETURN done;
  1484.   END;
  1485. END handleMsgKey;
  1486.  
  1487. PROCEDURE closeMsgWindow (wdw, vdiH : INTEGER; special : ADDRESS; force : BOOLEAN) : BOOLEAN;
  1488.   VAR ptr : msgWdwPtr;
  1489.       full    : GrafBase.Rectangle;
  1490. BEGIN
  1491.   ptr := msgWdwPtr (special);
  1492.   WITH ptr^ DO
  1493.     WdwManager.GetWdwSize (wdw, full); (* Gr”že des Fensters abfragen *)
  1494.     v.bool := ConfVars.SetConfigRect (cfgWindow, full);
  1495.     v.bool := ConfVars.SetConfigInt (cfgFont, font);
  1496.     v.bool := ConfVars.SetConfigInt (cfgFontSize, fontSize);
  1497.     v.bool := ConfVars.SetConfigInt (cfgLeftOffset, pixOffset);
  1498.     v.bool := ConfVars.SetConfigInt (cfgLineDist, lineDist);
  1499.     FontSelect.UnloadFonts (vdi);
  1500.   END;
  1501.   ptr^.wdw := -1;
  1502.   ptr^.vdi := -1;
  1503.   RETURN TRUE
  1504. END closeMsgWindow;
  1505.  
  1506. PROCEDURE topMsgWdw (wdw, vdiH : INTEGER; special : ADDRESS) : BOOLEAN;
  1507. BEGIN
  1508.   RETURN TRUE;
  1509. END topMsgWdw;
  1510.  
  1511. PROCEDURE untopMsgWdw (wdw, vdiH : INTEGER; special : ADDRESS);
  1512. END untopMsgWdw;
  1513.  
  1514. PROCEDURE updateMsgWdw (wdw, vdiH : INTEGER; special : ADDRESS; update : BOOLEAN);
  1515. BEGIN
  1516.   IF update
  1517.   THEN
  1518.     MagicAES.WindUpdate (MagicAES.BEGUPDATE);
  1519.     mtAppl.MouseOff();
  1520.   ELSE
  1521.     mtAppl.MouseOn();
  1522.     MagicAES.WindUpdate (MagicAES.ENDUPDATE);
  1523.   END;
  1524. END updateMsgWdw;
  1525.  
  1526. PROCEDURE setMsgWork (wdw, vdiH : INTEGER; special : ADDRESS; doc : GrafBase.LongRect; slided : BOOLEAN);
  1527.   VAR ptr : msgWdwPtr;
  1528. BEGIN
  1529.   ptr := msgWdwPtr (special);
  1530.   WITH ptr^ DO
  1531.     leftOffset := SHORT(doc.x);
  1532.     startPos   := SHORT(doc.y);
  1533.   END;
  1534. END setMsgWork;
  1535.  
  1536. PROCEDURE getMsgScroll (wdw, vdiH : INTEGER; special : ADDRESS; VAR work : GrafBase.Rectangle);
  1537.   VAR ptr       : msgWdwPtr;
  1538.       full      : GrafBase.Rectangle;
  1539. BEGIN 
  1540.   ptr := msgWdwPtr (special);
  1541.   AdjustTreePos (work, ptr^.butWork);
  1542.   DEC (work.h, butBox^[0].obHeight+1);
  1543.   INC (work.y, butBox^[0].obHeight+1);
  1544.   WITH work DO
  1545.     ptr^.windLines := (BinOps.LowerInt(y+h-1, INTEGER(mtAppl.MaxHeight-1)) - y+1) DIV (2*ptr^.charHeight+lineDist); 
  1546.     WdwManager.SetScrollParms (wdw, w-ptr^.charWidth, ptr^.windLines-1, ptr^.charWidth, 1);
  1547.     WITH ptr^ DO
  1548.       msgWork := work;
  1549.     END;
  1550.   END;
  1551.   IF wdw >= 0
  1552.   THEN
  1553.     WdwManager.GetWdwSize (wdw, full); (* Gr”že des Fensters abfragen *)
  1554.     v.bool := ConfVars.SetConfigRect (cfgWindow, full);
  1555.   END;
  1556. END getMsgScroll;
  1557.  
  1558. PROCEDURE snapMsgWdw (wdw, vdiH : INTEGER; special : ADDRESS; VAR work : GrafBase.Rectangle);
  1559.   CONST minWindWidth = 128;
  1560.         minWindHeight = 48;
  1561.   VAR ptr       : msgWdwPtr;
  1562. BEGIN
  1563.   ptr := msgWdwPtr (special);
  1564.   WITH ptr^ DO
  1565.     AdjustTreePos (work, butWork);
  1566.     IF ~inOpen
  1567.     THEN
  1568.       WITH work DO
  1569.         DEC (h, butWork.h);
  1570.         INC (h);            (* Um Rundungsfehler zu vermeiden *)
  1571.         h := ((h+lineDist) DIV (2*charHeight+lineDist)  ) * (2*charHeight+lineDist);
  1572.         WHILE w < minWindWidth DO INC(w, charWidth) END;
  1573.         WHILE h < minWindHeight DO INC(h, 2*charHeight+lineDist) END;
  1574.         windLines := (BinOps.LowerInt(y+h-1, INTEGER(mtAppl.MaxHeight-1)) - y+1) DIV (2*charHeight+lineDist); 
  1575.         msgWork := work;
  1576.         INC (work.h, butWork.h);
  1577.         WdwManager.SetScrollParms (wdw, w-charWidth, windLines-1, charWidth, 1);
  1578.       END;
  1579.     END;
  1580.   END;
  1581. END snapMsgWdw;
  1582.  
  1583. PROCEDURE hideMsgWdw (wdw, vdiH : INTEGER; special : ADDRESS; hide : BOOLEAN);
  1584.   VAR ptr       : msgWdwPtr;
  1585.       full      : GrafBase.Rectangle;
  1586. BEGIN 
  1587.   ptr := msgWdwPtr (special);
  1588.   ptr^.isHidden := hide;
  1589. END hideMsgWdw;
  1590.  
  1591.  
  1592. (*-------------- exportierte Funktionen -----------------------*)
  1593.  
  1594. (*$H+*)
  1595. PROCEDURE msgOpen (errorMsg: BOOLEAN);
  1596. (* Bringt das Fenster mit der Nachrichtenbersicht 
  1597.  * in den Vordergrund bzw. ”ffnet es, falls noch nicht 
  1598.  * offen. Die Nachricht muž dann im Fenster ausgew„hlt 
  1599.  * werden.
  1600.  *)
  1601.   VAR ptr       : msgWdwPtr;
  1602.       work      : GrafBase.Rectangle;
  1603.       comps     : BITSET;
  1604.       i         : INTEGER;
  1605.       title     : ARRAY [0..80] OF CHAR;
  1606. BEGIN
  1607.   IF msgWindow.wdw >= 0
  1608.   THEN 
  1609.     IF msgWindow.isHidden
  1610.     THEN
  1611.       v.bool := WdwManager.ShowWindow (msgWindow.wdw);
  1612.     ELSE
  1613.       WdwManager.TopWindow (msgWindow.wdw);
  1614.     END;
  1615.   ELSE
  1616.     ptr := ADR(msgWindow);
  1617.     ConfVars.GetConfDefRect (cfgWindow, ptr^.msgWork, EditTypes.deskSize);
  1618.     ConfVars.GetConfDefInt (cfgLeftOffset, pixOffset, 8);
  1619.     pixOffset := BinOps.HigherInt (0, pixOffset);
  1620.     ConfVars.GetConfDefInt (cfgLineDist, lineDist, 2);
  1621.     lineDist := BinOps.HigherInt (0, lineDist);
  1622.     (* Fensterkomponenten setzen *)
  1623.     comps := {MagicAES.NAME..MagicAES.HSLIDE};
  1624.     (* Infozeile brauchen wir nicht *)
  1625.     EXCL (comps, MagicAES.INFO);
  1626.     
  1627.     ptr^.wdw := -1;
  1628.     ptr^.maxPos := Messages.messages - 1;
  1629.     ptr^.list := Messages.msgArray;
  1630.     IF (Messages.msgArray = NIL) OR (Messages.messages <= 0) THEN 
  1631.       IF errorMsg THEN MTE.info (MTE.noMsgAlt); END;
  1632.       RETURN 
  1633.     END;
  1634.     FOR i := 0 TO Messages.messages - 1 DO
  1635.       Messages.msgArray^[i].selected := FALSE;
  1636.     END;
  1637.     careForButtons (ptr, FALSE);
  1638.     ptr^.charHeight  := 16;
  1639.     ptr^.charWidth   := 8;
  1640.     inOpen := TRUE;
  1641.     (* Fenster ”ffnen *)
  1642.     Strings.Assign (msgWindowTitle, title, v.bool);
  1643.     ConfVars.GetConfDefBool (cSetAppName, v.bool, TRUE);
  1644.     IF CatGlobal.multiTask & v.bool
  1645.     THEN
  1646.       Strings.Insert (msgWindowTitle0, 0, title, v.bool);
  1647.     END;
  1648.     IF WdwManager.OpenWindow (clickInMsgWindow, handleMsgKey, WdwManager.handleTimerProc (NIL),
  1649.                               EditTypes.deskSize, ptr^.msgWork, comps, TRUE, 
  1650.                               '', title, snapMsgWdw, closeMsgWindow, 
  1651.                               drawMsgWdw, topMsgWdw, untopMsgWdw, updateMsgWdw,
  1652.                               setMsgWork, getMsgScroll, hideMsgWdw, pixOffset, ptr, 
  1653.                               FALSE, TRUE, TRUE, TRUE, ptr^.wdw, ptr^.vdi)
  1654.     THEN
  1655.       WITH ptr^ DO
  1656.         inOpen := FALSE;
  1657.         isHidden := FALSE;
  1658.         (* Font aus Configvariablen lesen und setzen *)
  1659.         ConfVars.GetConfDefInt (cfgFont, font, 1);
  1660.         ConfVars.GetConfDefInt (cfgFontSize, fontSize, 10);
  1661.         startPos := 0;
  1662.         leftOffset := 0;
  1663.         maxWidth   := 0;
  1664.         (* Noch ein bižchen was fr die Window-Library *)
  1665.         WdwManager.SetNewDocument (wdw, GrafBase.LongRect{LONG(leftOffset), startPos, LONG(maxWidth), maxPos}, FALSE);
  1666.         (* Fonts laden *)
  1667.         FontSelect.LoadFonts (vdi, v.int);
  1668.         (* Font setzen *)
  1669.         iMsgSetFont (wdw, font, fontSize, FALSE);
  1670.         (* Jetzt noch ein paar andere VDI-Variablen setzen *)
  1671.         v.int := MagicVDI.SetFillstyle (vdi, MagicVDI.Full);
  1672.         v.int := MagicVDI.SetFillinterior (vdi, MagicVDI.Full);
  1673.         v.int := MagicVDI.SetFillcolor (vdi, CatGlobal.msgBackCol);
  1674.         (* Schreibmodus setzen *)
  1675.         v.int := MagicVDI.SetWritemode (vdi, MagicVDI.REPLACE);
  1676.         sel := -1;
  1677.       END;
  1678.     ELSE
  1679.       inOpen := FALSE;
  1680.       ptr^.wdw := -1;
  1681.     END;
  1682.   END;
  1683. END msgOpen;
  1684. (*$H=*)
  1685.  
  1686. PROCEDURE msgClose (wdw : INTEGER);
  1687. (* Ein Stichwortlistenfenster wird geschlossen *)
  1688. BEGIN
  1689.   IF msgWindow.wdw = wdw
  1690.   THEN
  1691.     v.bool := WdwManager.CloseWindow (wdw, TRUE);
  1692.   END;
  1693. END msgClose;
  1694.  
  1695. PROCEDURE msgWindowTop (wdw : INTEGER) : BOOLEAN;
  1696. (* Ist ein Stichwortlistenfenster oben? *)
  1697. BEGIN
  1698.   RETURN (msgWindow.wdw = wdw) & (msgWindow.wdw >= 0);
  1699. END msgWindowTop;
  1700.  
  1701. PROCEDURE msgSetFont (wdw: INTEGER; font, fontSize : INTEGER);
  1702. BEGIN
  1703.   iMsgSetFont (wdw, font, fontSize, TRUE);
  1704. END msgSetFont;
  1705.  
  1706. PROCEDURE msgSelectAll (wdw: INTEGER);
  1707. (* Selektiert alle Nachrichten in der Nachrichtenliste 
  1708.  *)
  1709.   VAR i : INTEGER;
  1710. BEGIN
  1711.   IF msgWindow.wdw = wdw
  1712.   THEN
  1713.     WITH msgWindow DO 
  1714.       FOR i := 0 TO Messages.messages - 1 DO 
  1715.         IF ~Messages.msgArray^[i].selected
  1716.         THEN
  1717.           (* Erledigt auch direkt den Redraw davon *)
  1718.           toggleEntry (ADR(msgWindow), i); 
  1719.         END;
  1720.       END;
  1721.     END;
  1722.     careForButtons (ADR(msgWindow), TRUE);
  1723.   END;
  1724. END msgSelectAll;
  1725.  
  1726. PROCEDURE msgSavePos();
  1727.   VAR num : INTEGER;
  1728.       varName : ARRAY [0..127] OF CHAR;
  1729.       full: GrafBase.Rectangle;
  1730.       max : INTEGER;
  1731. BEGIN
  1732.   IF msgWindow.wdw >= 0
  1733.   THEN
  1734.     WITH msgWindow DO 
  1735.       v.bool := ConfVars.SetConfigBool (cfgOpen, TRUE);
  1736.       WdwManager.GetWdwSize (wdw, full); (* Gr”že des Fensters abfragen *)
  1737.       v.bool := ConfVars.SetConfigRect (cfgWindow, full);
  1738.       v.bool := ConfVars.SetConfigInt (cfgFont, font);
  1739.       v.bool := ConfVars.SetConfigInt (cfgFontSize, fontSize);
  1740.       v.bool := ConfVars.SetConfigInt (cfgLeftOffset, pixOffset);
  1741.       v.bool := ConfVars.SetConfigInt (cfgLineDist, lineDist);
  1742.     END;
  1743.   ELSE
  1744.     v.bool := ConfVars.SetConfigBool (cfgOpen, FALSE);
  1745.   END;
  1746.   Messages.SaveEditPos(max);
  1747.   v.bool := ConfVars.SetConfigInt (cfgMax, max);
  1748. END msgSavePos;
  1749.  
  1750. PROCEDURE msgRestorePos ();
  1751.   VAR num : INTEGER;
  1752.       i   : INTEGER;
  1753.       varName : ARRAY [0..127] OF CHAR;
  1754.       idx     : INTEGER;
  1755.       max     : INTEGER;
  1756. BEGIN
  1757.   IF ConfVars.GetConfigBool (cfgOpen, v.bool) & v.bool
  1758.   THEN
  1759.     msgOpen(FALSE);
  1760.   END;
  1761.   ConfVars.GetConfDefInt (cfgMax, max, -1);
  1762.   FOR i := 0 TO max DO 
  1763.     Strings.Concat (cfgEdit, StrConv.IntToStr (i, 0), varName, v.bool);
  1764.     IF ConfVars.GetConfigInt (varName, num) & (Messages.FindMessage (i) >= 0)
  1765.     THEN
  1766.       idx := Messages.FindMessage (i);
  1767.       IF ~Messages.msgArray^[idx].hdrRead
  1768.       THEN
  1769.         Messages.ReadHdrInfo (Messages.msgArray^[idx], FALSE);
  1770.       END;
  1771.       Messages.OpenEditor (Messages.msgArray^[idx], FALSE, num, 0, FALSE);
  1772.     END;
  1773.   END;
  1774. END msgRestorePos;
  1775.  
  1776. PROCEDURE msgUpdateInfo ();
  1777. BEGIN
  1778.   (* MSGINFO.DAT neu einlesen *)
  1779.   IF Messages.msgArray # NIL THEN DEALLOCATE (Messages.msgArray, 0); END;
  1780.   Messages.messages := 0;
  1781.   Messages.usedNumbers := Messages.msgNumberSet{};
  1782.   Messages.ReadMessageInfo();
  1783.   IF Messages.messages = 0
  1784.   THEN
  1785.     IF msgWindow.wdw >= 0
  1786.     THEN
  1787.       msgClose(msgWindow.wdw);
  1788.     END;
  1789.   END;
  1790. END msgUpdateInfo;
  1791.  
  1792. PROCEDURE msgCloseAll(force : BOOLEAN): BOOLEAN;
  1793. BEGIN
  1794.   IF ~Messages.CloseAllEditors (force)
  1795.   THEN
  1796.     RETURN FALSE
  1797.   END;
  1798.   IF msgWindow.wdw >= 0
  1799.   THEN
  1800.     msgClose(msgWindow.wdw);
  1801.   END;
  1802.   RETURN TRUE;
  1803. END msgCloseAll;
  1804.  
  1805. PROCEDURE MsgSetList (list: ADDRESS; doRedrawWdw: BOOLEAN);
  1806. (* Setzt die Liste fr das Fenster
  1807.  *)
  1808. BEGIN
  1809.   msgWindow.list := list;
  1810.   IF doRedrawWdw & (msgWindow.wdw >= 0) & ~msgWindow.isHidden
  1811.   THEN
  1812.     (* Fenster ist offen *)
  1813.     WdwManager.FullRedrawWdw (msgWindow.wdw);
  1814.   END;
  1815. END MsgSetList;
  1816.  
  1817. PROCEDURE MsgSetMaxPos (maxPos : INTEGER; doRedrawWdw: BOOLEAN);
  1818. (* Setzt die Maximalposition fr die Liste
  1819.  *)
  1820. BEGIN
  1821.   msgWindow.maxPos := maxPos; 
  1822.   IF msgWindow.startPos > msgWindow.maxPos 
  1823.   THEN 
  1824.     msgWindow.startPos := BinOps.HigherInt (0, msgWindow.maxPos-1) 
  1825.   END;
  1826.   IF doRedrawWdw
  1827.   THEN
  1828.     IF msgWindow.wdw >= 0
  1829.     THEN
  1830.       WITH msgWindow DO
  1831.         WdwManager.SetWdwDocument (wdw, GrafBase.LongRect{LONG(leftOffset), startPos, LONG(maxWidth), maxPos});
  1832.         WdwManager.FullRedrawWdw (msgWindow.wdw);
  1833.       END;
  1834.     END;
  1835.   END;
  1836. END MsgSetMaxPos;
  1837.  
  1838. PROCEDURE MsgCloseIfOpen ();
  1839. (* Schliežt das Fenster, falls es offen ist
  1840.  *)
  1841. BEGIN
  1842.   IF msgWindow.wdw >= 0
  1843.   THEN
  1844.     v.bool := WdwManager.CloseWindow (msgWindow.wdw, TRUE);
  1845.   END; 
  1846. END MsgCloseIfOpen;
  1847.  
  1848. PROCEDURE MsgUpdateButtons ();
  1849. (* Aktualisiert die Buttons im Anzeigefenster passend zur Selektion 
  1850.  *)
  1851. BEGIN
  1852.   careForButtons (ADR(msgWindow), TRUE);
  1853. END MsgUpdateButtons;
  1854.  
  1855. PROCEDURE MsgRedrawEntry (idx: INTEGER);
  1856. (* Erzwingt das Neuzeichnen des Eintrags mit der Nummer idx 
  1857.  * im Fenster
  1858.  *)
  1859. BEGIN
  1860.   redrawEntry (idx);
  1861. END MsgRedrawEntry;
  1862.  
  1863. PROCEDURE MsgDeselectAll ();
  1864. (* Setzt den Selectindex auf -1 und erzwingt ggf. einen Redraw
  1865.  *)
  1866. BEGIN
  1867.   IF (msgWindow.wdw >= 0) & (msgWindow.sel >= 0) & ~(msgWindow.isHidden)
  1868.   THEN
  1869.     msgWindow.sel := -1;
  1870.     careForButtons (ADR(msgWindow), FALSE);
  1871.     WdwManager.FullRedrawWdw (msgWindow.wdw);
  1872.   END;
  1873. END MsgDeselectAll;
  1874.  
  1875. PROCEDURE InitMessageManager ();
  1876. (* Initialisiert das Modul und einige wichtige Daten
  1877.  * Ruft intern auch die Initialisierung vom Modul Messages auf
  1878.  *)
  1879.   VAR i : INTEGER;
  1880. BEGIN
  1881.   butBox := MausTauschrsc.TreeAddr^[MausTauschrsc.msgctrl];
  1882.   distSel := MausTauschrsc.TreeAddr^[MausTauschrsc.distribx];
  1883.   IF init # 23023
  1884.   THEN 
  1885.     v.bool := mtDials.NewDial (butBox);
  1886.   END;
  1887.   FOR i := MausTauschrsc.ctrledit TO MausTauschrsc.ctrldis2 DO
  1888.     mtUtils.InclState (butBox, i, MagicAES.DISABLED);
  1889.   END;
  1890.   init := 23023;
  1891.   Messages.InitMessages();
  1892. END InitMessageManager;
  1893.  
  1894. BEGIN
  1895.   msgWindow.wdw := -1;
  1896.   init := 0;
  1897. END MsgWindow.
  1898.